window.DataGrid = function() {
    /***
     * @private
     */
    this.events = new Object();

        /***
        * @private
        */
    this.doubleClickEmulation = {};

    /***
     *@private
     */
    this.selectedRow = {};
    /***
    * @private
    */
    this.dataProvider = new Collection();
    /***
    * @private
    */
    this.container = new Object();
    /***
    * @private
    */
    this.nextSibling = null;

    /***
        * @private
        */
    this.component = $(document.createElement("table"));
        /***
        * @private
        */
    this.thead = $(document.createElement("thead"));
        /***
        * @private
        */
    this.tbody = $(document.createElement("tbody"));

        // Set default attributes of table
    this.component.attr("border",0);
    this.component.attr("cellpadding",0);
    this.component.attr("cellspacing",0);
    this.component.attr("unselectable","on");
    this.component.addClass("display");

    this.component.append(this.thead);
    this.component.append(this.tbody);

    this.setContainer = function(container) {
        this.container = container;
        if (this.nextSibling.length > 0) {
            this.component.insertBefore(this.nextSibling);
        } else {
            this.container.append(this.component);
        }
    }

    /***
    * @private
    */
    this.setElement = function (o) {
        this.element = o;
        this.nextSibling = o.next();
        this.setContainer(o.parent());

        var columns = $(this.element).find("DataGridColumn");

        for(var i = 0; i < columns.length; i++) {
           var column = new DataGridColumn(), col = columns[i];
           column.setGrid(this);
           for(var j = 0; j < col.attributes.length; j++){
                try {
                    column["set"+(new $.fn.mxtags).toCamel(col.attributes[j].nodeName)](col.attributes[j].nodeValue);
                } catch(ex) {
                    
                }
            }
           this.addColumn(column);
        }

        this.element.remove();
    }

    /***
    * @private
    */
    this.setId = function(value) {
        this.name = value;
        this.id = value;
        this.component.attr("id",value);
        window[value] = this;
    }

    /***
    * @private
    */
    this.makeComponentData = function(){
        var tr = $(document.createElement("tr"));
        for(var i = 0; i < this.columns.length; i++) {
            var th = $(document.createElement("th"));
            th.html(this.columns[i].headerText);
            th.attr("width", this.columns[i].width);
            th.attr("align", this.columns[i].align);
            if (i == 0) th.addClass("dataGridFirstTh");
            th.addClass("sorting");
            tr.append(th);
        }

        this.thead.html("");
        this.thead.append(tr);
        
        this.refresh();
    }

        /***
        * @private
        */
    this.labelFunction = function(item, column) {
        return item[column.dataField];
    }

        /***
        * @private
        */
    this.refresh = function() {
        this.tbody.html("");

        for(var i = 0; i < this.dataProvider.size(); i++) {

            var tr = $(document.createElement("tr"));
            if (i % 2) tr.addClass("odd");
            else tr.addClass("even");
            tr[0].grid = this;

            tr.click(function(event){this.grid.fire(DataGridEvent.ROW_CLICK, event);});
            tr.dblclick(function(event){this.grid.fire(DataGridEvent.ROW_DBLCLICK, event);});

            for(var j = 0; j < this.columns.length; j++) {
                var td = $(document.createElement("td"));
                td.html(this.columns[j].labelFunction(this.dataProvider.getItemAt(i), this.columns[j]))
                if (j == 0) td.addClass("dataGridFirstTd");
                tr.append(td);
            }

            this.tbody.append(tr);
        }
    }

    this.name = "unnamed";

    this.columns = new Array();

    this.setWidth = function(value) {
        this.component.css("width",value);
    }

    this.setHeight = function(value) {
        this.component.css("height",value);
    }

    this.setDataProvider = function(dataProvider) {
        this.dataProvider = (dataProvider instanceof Collection)  ? dataProvider : eval(dataProvider);
        this.dataProvider.owner = this;
        this.dataProvider.bind(CollectionEvent.DATA_CHANGED, function(event, eventData){event.target.owner.dataProviderChangedHandler(event, eventData);});
        this.refresh();
    }

    this.dataProviderChangedHandler = function(event, eventData) {
        this.makeComponentData();
    }

    this.setLabelfunction = function(func) {
        this.labelFunction = (func instanceof Function)  ? func : eval(func);
        this.refresh();
    }

    this.addColumn = function(column) {
        if (!(column instanceof DataGridColumn)) {
            throw new Error("O parametro passado não é uma instância de DataGridColumn");
            return null;
        } else {
            this.columns.push(column);
        }
    }

        /***
     * Adiciona um evento à instancia do objeto
     * @param eventName
     * @param callBack
     * @return Collection
     */
    this.bind = function(eventName, callBack) {
        this.events[eventName] = new Object();
        this.events[eventName].callBack = callBack;
        return this;
    }

    /***
     * Dispara o evento indicado
     * @param eventName
     * @param event
     * @return Collection
     */
    this.fire = function(eventName, event) {
        if (eventName == DataGridEvent.ROW_CLICK) {
            if (DataGridEvent.DBLCLICK_EMULATION) return null;

            DataGridEvent.DBLCLICK_EMULATION = window.setTimeout(function(){
                DataGridEvent.DBLCLICK_EMULATION = null;
            },500);

            $(".dataGridItemSelected").removeClass("dataGridItemSelected");

            if (this.selectedRow != event.currentTarget) {
                $(event.currentTarget).addClass("dataGridItemSelected");
                this.selectedRow = event.currentTarget;
            } else {
                this.selectedRow = {};
            }
        } else if (eventName == DataGridEvent.ROW_DBLCLICK) {
            if(DataGridEvent.DBLCLICK_EMULATION){
                 clearTimeout(DataGridEvent.DBLCLICK_EMULATION);
                 DataGridEvent.DBLCLICK_EMULATION = null;
             }
        }

        if (this.events[eventName]) {
            this.events[eventName].callBack(event);
        }

        return this;

    }
        this.selectedIndex = function() {
        return this.tbody.find("tr").index(this.selectedRow);
    }

    this.selectedItem = function () {
        return this.dataProvider.getItemAt(this.tbody.find("tr").index(this.selectedRow));
    }
}

var DataGridEvent = {

    /**
     * Evento disparado ao clicar na row da <code>DataGrid</code>
     * @example
     * function clickHandler(event) {
     *      alert("event");
     * }
     * var myGrid = new DataGrid();
     *     myGrid.bind(DataGridEvent.ROW_CLICK, clickHandler);
     * @eventType DataGridEvent.ROW_CLICK
     */
    ROW_CLICK : "rowClick=",
    /**
     * Evento disparado ao clicar duas vezes na row da <code>DataGrid</code>
     * @example
     * function doubleClickHandler(event) {
     *      alert("event");
     * }
     * var myGrid = new DataGrid();
     *     myGrid.bind(DataGridEvent.ROW_DBLCLICK, doubleClickHandler);
     * @eventType DataGridEvent.ROW_DBLCLICK
     */
     ROW_DBLCLICK : "rowDBLClick=",
     
    /***
     * @private
     */
    DBLCLICK_EMULATION : null
};